<template>
  <!-- @click.stop="onBlankClick($event)" -->
  <div class="columns-container six-px-scroll-x" @scroll="containerScroll">
    <data-column
      v-for="(column, i) in tableColumns"
      ref="dataColumn"
      :key="`${column.name}`"
      :tools="isPreviewMode ? null : []"
      :column="column"
      :task-id="-7"
      :table-name="tableName"
      :visible="i >= visibleRange[0] && i <= visibleRange[1]"
      :cache="columnQueryStatCache"
      :column-filters="columnFilters"
      :column-list="tableColumns"
      :selected-columns="selectedColumns"
      :contextmenu-enable="false"
      :is-visitor="isVisitor"
      :project-id="projectId"
      class="column-card"
      @bar-click="onColumnBarFilter"
      @click="onDataColumnClick($event, column, i)"
    />
    <div
      v-show="
        (!tableColumns || tableColumns.length === 0) && !isTableDetailLoading
      "
      class="empty-info"
    >
      <img alt="" src="@/assets/view/empty2.png" />
      <p>暂无数据 请确认图层数据！</p>
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Watch, Prop } from 'vue-property-decorator'
import DataColumn from '@/components/studio/data/node-edit-panel/DataColumn.vue'
import { debounce, isEqual, uniq } from 'lodash'
import GisStore, { IColumn } from '@/store/modules/gis'
import SelectionType from '@/util/selection-type'

@Component({
  components: {
    DataColumn,
  },
})
export default class GisLayerDataColumns extends Vue {
  @Prop({ default: false }) public isVisitor!: boolean // 是否访客模式

  private lastClickedColumnIndex: number | null = null // 最后点击的列
  private oldSelectedColumns: any[] = [] // 历史选择的列
  private columnWidth = 180 // 列宽度
  private pageSize = 6 // 可视区域可加载个数
  private visibleRange = [0, 0] // 数据列可视范围，[start index，end index]
  private columnQueryStatCache = {} // 缓存

  // 项目 id projectId
  private get projectId() {
    return GisStore.projectId
  }

  // 全部表列 col 信息
  private get tableColumns(): any[] {
    return GisStore.layerTableColumns
  }

  // 选择的图层
  private get selectLayer() {
    return GisStore.selectLayer
  }

  // 选择的列
  private get selectedColumns(): any[] {
    return GisStore.selectedColumns
  }

  // loading
  private get isTableDetailLoading() {
    return GisStore.isTableDetailLoading
  }

  // 查询数据的表名取决于当前历史记录的表名，没有的话取 selectLayer 的表名
  private get tableName(): string {
    return GisStore.selectLayer?.viewName
  }

  // TODO

  // 查询数据需要的接口参数，用于筛选数据
  private get columnFilters() {
    return GisStore.columnFilters
  }
  /**
   * 预览表数据的时候视为预览模式（禁止一些修改操作）
   */
  private get isPreviewMode(): boolean {
    return false
  }

  /**
   * 是否按住ctrl多选模式：win下按住ctrl键，mac下按住command键
   */
  private isCtrlSelect(event: MouseEvent) {
    if (this.isMac) {
      return event.metaKey
    }
    return event.ctrlKey
  }

  private get isMac() {
    const { userAgent } = window.navigator
    return userAgent.includes('Mac OS X')
  }

  @Watch('tableColumns')
  private onTableColumnsChange(newValue: any[]) {
    /**
     * 利用nextTick避免DataColumn.vue 组件里columnChange和visibleChange的重复接口操作
     * 1、columnChange时，visibleRange为[-1,-1]
     * 2、nextTick里visibleChange触发查询
     */
    this.$nextTick(() => {
      if (newValue.length > 0) {
        this.initFetchSetting() // 初始化可见区域范围计算
      }
    })
  }

  @Watch('tableName')
  private onTableChange() {
    GisStore.setColumnFilters([])
    this.clearSelection()
    this.visibleRange = [-1, -1] // 把列都设为不可见，避免列信息更新后不必要的 queryStat
    this.columnQueryStatCache = {} // 清空缓存
  }

  /**
   * 初始化分页加载获取数据相关的配置
   */
  public initFetchSetting() {
    const { width: containerWidth } = this.$el.getBoundingClientRect()
    const pageSize = Math.ceil(containerWidth / this.columnWidth) + 1
    this.pageSize =
      pageSize > this.tableColumns.length ? this.tableColumns.length : pageSize
    const startIndex = 0
    this.visibleRange = [startIndex, startIndex + this.pageSize]
  }

  /**
   * 根据列名返回列索引
   */
  private getColumnIndex(columnName: string) {
    if (this.tableColumns.length === 0) {
      return 0
    }
    return this.tableColumns.findIndex((column) => column.name === columnName)
  }

  // 滚动防抖
  private containerScroll = debounce(() => this._handleContainerScroll(), 300)

  /**
   * 容器滚动
   */
  private _handleContainerScroll() {
    const container = this.$el
    const { width } = container.getBoundingClientRect()
    const { scrollLeft } = container
    const pageSize = Math.ceil(width / this.columnWidth)
    const leftInvisibleIndex = Math.floor(scrollLeft / this.columnWidth) - 1
    this.visibleRange = [leftInvisibleIndex, leftInvisibleIndex + pageSize]
  }

  private clearSelection() {
    this.lastClickedColumnIndex = null
    this.oldSelectedColumns = []
    GisStore.clearSelectedColumns()
  }

  /**
   * bar点击后筛选操作
   */
  private onColumnBarFilter(filters: any) {
    // 预览模式
    if (this.isPreviewMode) {
      return
    }
    if (!isEqual(filters, GisStore.columnFilters)) {
      GisStore.setColumnFilters(filters)
    }
  }

  private onDataColumnClick(
    event: MouseEvent,
    column: IColumn,
    index: number,
    formulaFlag?: boolean
  ) {
    //  若来自menu formula new column click, formulaFlag 为true ，且设置OnlyShowFormulaCard 为 true
    if (formulaFlag) {
      //  TBD 若该列已经被选中 则 return 不再重复点击
      if (
        GisStore.tableSelectColumns.length > 0 &&
        column.name === GisStore.tableSelectColumns[0].name
      ) {
        GisStore.setTableSelectionType(SelectionType.columns)
        return
      }
    }
    // 预览模式
    if (this.isPreviewMode) {
      return
    }

    // 非多选
    if (!event.shiftKey) {
      if (this.isCtrlSelect(event)) {
        GisStore.toggleSelectedColumn(column)
      } else if (
        this.selectedColumns.length === 1 &&
        this.selectedColumns[0] === column
      ) {
        GisStore.setSelectedColumns([])
      } else {
        GisStore.setSelectedColumns([column])
      }
      this.lastClickedColumnIndex = index
      this.oldSelectedColumns = this.selectedColumns
      // 多选
    } else {
      const index2 = this.lastClickedColumnIndex ?? 0
      const columns = this.tableColumns.slice(
        Math.min(index, index2),
        Math.max(index, index2) + 1
      )
      GisStore.setSelectedColumns(
        uniq([...this.oldSelectedColumns, ...columns])
      )
    }

    GisStore.clearTableSelection() // 先清除表格的选择状态
    this.$nextTick(() => {
      if (this.selectedColumns.length > 0) {
        // 选择列
        GisStore.setTableSelectionType(SelectionType.columns)
        GisStore.setTableSelectColumns(this.selectedColumns)
      } else {
        GisStore.setTableSelectionType(SelectionType.none)
      }
    })
  }
}
</script>

<style lang="less" scoped>
@import '@/styles/scroll-bar';

.columns-container {
  background: #fafafc;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 8px 9px;
  user-select: none;

  &::after {
    content: '';
    padding-right: 9px;
  }

  .empty-info {
    align-items: center;
    display: flex;
    flex: 1;
    flex-direction: column;
    justify-content: center;
    text-align: center;

    > p {
      margin-top: 12px;
    }
  }
}
</style>
